import sys
import multiprocessing
import time
import asyncio
import threading
from qasync import asyncSlot
from PyQt5.QtWidgets import QPushButton, QVBoxLayout, QWidget, QApplication, QMainWindow

def long_running_task(queue):
    try:
        for i in range(10):
            time.sleep(1)
            # 检查是否有终止命令
            if not queue.empty():
                cmd = queue.get_nowait()
                if cmd == 'terminate':
                    queue.put(('error', 'Terminated by user'))
                    return
        queue.put(('success', 'Task completed'))
    except Exception as e:
        queue.put(('error', str(e)))
    finally:
        queue.close()

class Worker:
    def __init__(self):
        self.queue = multiprocessing.Queue()
        self.process = None

    async def run_task(self):
        self.process = multiprocessing.Process(target=long_running_task, args=(self.queue,))
        self.process.start()
        loop = asyncio.get_event_loop()
        future = loop.create_future()

        def thread_target():
            try:
                result = self.queue.get()
                loop.call_soon_threadsafe(future.set_result, result)
            except Exception as e:
                loop.call_soon_threadsafe(future.set_exception, e)

        threading.Thread(target=thread_target, daemon=True).start()

        async def check_process():
            while True:
                await asyncio.sleep(0.1)
                if not self.process.is_alive():
                    if not future.done():
                        if self.process.exitcode != 0:
                            future.set_exception(Exception(f"Process exited with code {self.process.exitcode}"))
                        else:
                            future.set_exception(Exception("Process exited without result"))
                    break

        asyncio.create_task(check_process())
        return await future

    def terminate(self):
        if self.process and self.process.is_alive():
            try:
                self.queue.put('terminate')
            except:
                pass
            self.process.terminate()

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.worker = Worker()
        self.setup_ui()

    def setup_ui(self):
        widget = QWidget()
        layout = QVBoxLayout()
        self.start_btn = QPushButton("Start Task")
        self.stop_btn = QPushButton("Stop Task")
        layout.addWidget(self.start_btn)
        layout.addWidget(self.stop_btn)
        widget.setLayout(layout)
        self.setCentralWidget(widget)

        self.start_btn.clicked.connect(self.on_start_clicked)
        self.stop_btn.clicked.connect(self.on_stop_clicked)

    @asyncSlot()
    async def on_start_clicked(self):
        try:
            result = await self.worker.run_task()
            status, data = result
            if status == 'success':
                print("Success:", data)
            else:
                print("Error:", data)
        except Exception as e:
            print("Exception:", e)

    def on_stop_clicked(self):
        self.worker.terminate()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    loop = asyncio.get_event_loop()
    app.closeEvent = lambda event: loop.stop()
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())